package com.tzh.utils;

import org.springframework.util.StringUtils;

public class ResultDto<T> {

    private static final ThreadLocal<ResultDto<?>> thread = new ThreadLocal<ResultDto<?>>();

    private String code = "0000";

    private String msg = "操作成功";

    private T obj = null;

    /**
     * volatile和synchronized的区别
     * volatile本质是在告诉jvm当前变量在寄存器（工作内存）中的值是不确定的，需要从主存中读取； synchronized则是锁定当前变量，只有当前线程可以访问该变量，其他线程被阻塞住。
     * volatile仅能使用在变量级别；synchronized则可以使用在变量、方法、和类级别的
     * volatile仅能实现变量的修改可见性，不能保证原子性；而synchronized则可以保证变量的修改可见性和原子性
     * volatile不会造成线程的阻塞；synchronized可能会造成线程的阻塞。
     * volatile标记的变量不会被编译器优化；synchronized标记的变量可以被编译器优化
     * *********
     * //--------
     * <T> T表示返回值是一个泛型，传递啥，就返回啥类型的数据，而单独的T就是表示限制你传递的参数类型，
     * 这个案例中，通过一个泛型的返回方式，获取每一个集合中的第一个数据， 通过返回值<T> T 和T的两种方法实现
     * //----------------
     * 如果希望 getMax 方法的返回值类型为 T，就要这样去定义getMax方法：
     * public T getMax()
     * 如果希望 getMax 方法返回值的类型由调用者决定，那么就这么去定义 getMax 方法：
     * public <A> A getMax() {
     * return (A)result;
     */
    public static <T> ResultDto<?> setFail(String msg) {
        ResultDto<?> localDto = thread.get();
        if (localDto == null) {
            synchronized (ResultDto.class) {
                if (localDto == null) {
                    localDto = new ResultDto<T>("9999", StringUtils.isEmpty(msg) ? "操作失败" : msg, null);
                    thread.set(localDto);
                }
            }
        }
        localDto.setCode("9999");
        localDto.setMsg(msg);
        localDto.setObj(null);
        return localDto;
    }

    @Override
    public String toString() {
        return "ResultDto{" +
                "code='" + code + '\'' +
                ", msg='" + msg + '\'' +
                ", obj=" + obj +
                '}';
    }

    /**
     * @param <T>
     * @return
     */
    public static <T> ResultDto<T> setSuccess(T data) {
        ResultDto<T> localDto = new ResultDto<T>();
        localDto.setCode("0000");
        localDto.setMsg("操作成功");
        localDto.setObj(data);
        return localDto;
    }


    private ResultDto() {
        super();
    }


    private ResultDto(String code, String msg, T obj) {
        super();
        this.code = code;
        this.msg = msg;
        this.obj = obj;
    }


    public String getCode() {
        return code;
    }

    private void setCode(String code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getObj() {
        return obj;
    }

    private void setObj(T data) {
        obj = data;
    }


}
